
package classes;

// tutte le funzioni usate per trattare le vertexList e per verificare la convessità (sfrutta i metodo LeftON)

class VertexList {
  int n;              // numero di vertici che compongono la lista: 0 se vuota
  Vertex head;

  VertexList() {
    head = null;
    n = 0;
  }
  

 public Vertex GetElement(int index)      //ritorna il vertice i-esimo
 {
   
   Vertex v = new Vertex();
   if (index <= n)
   {
     v = head;
     for (int i = 0; i < index; i++)
       v = v.next;
     
   }
   else v = new Vertex(10000, 10000);    //se passiamo un indice > n restituiamo un vertice particolare con coordinate (1000,1000) 
   
   return v;
 }



  public void InitHead( Vertex h )      //quando (head==null), inizializza l'head!
  {
    head = new Vertex();
    head = h;
    head.next = head.prev = head;
    n = 1;
  }
  
  

  public void ClearVertexList()        //mettiamo a null il puntatore al primo vertice, così cancelliamo la VertexList
  {
    if (head != null)
      head = null;
    n = 0;
  }

  
  
  public void InsertBeforeHead( Vertex ver )     //Inserts newV before head, chiama InsertBefore
  {
    if ( head == null )
	InitHead( ver );
    else {
        InsertBefore ( ver, head );
    }
  }

  
  
  public void InsertBefore( Vertex newV , Vertex oldV ) { 	  //Inserts newV before oldV	
    if ( head == null )                                           //se prima era 1(head)-2-3 e sia oldv=1 otteniamo 1-2-3-newv-1
	InitHead( newV );
    else {
        oldV.prev.next = newV;		
    	newV.prev = oldV.prev;		
    	newV.next = oldV;			       
    	oldV.prev = newV;
	n++;
    }
  }
  

  public void SetVertex(int x, int y)    //crea il vertice con coordinate (x,y) e lo inserisce prima dell'Head
  { 
    Vertex v = new Vertex( x, y );
    InsertBeforeHead( v );
  }


  
  

  public void Delete( Vertex ver ) 
  {
    if ( head == head.next )       //se esiste solo l'head lo poniamo a null
      head = null;
    else if ( ver == head )        //se il vertice da eliminare è head facciamo head quello successivo
      head = head.next;

    ver.prev.next = ver.next;      //il nodo da eliminare viene isolato, collegando il nodo prima con quello dopo
    ver.next.prev = ver.prev;
    n--;
  }
  

  /*Makes a copy of present list
   */
  public void ListCopy(VertexList list)    //fa una copia della lista presente su una nuova lista passata come parametro
  {
    Vertex temp1 = head, temp2;
    do {
      temp2 = new Vertex();               // crea un nuovo vertice
      temp2.v = temp1.v;                  // Riempie il vertice con lo stesso Pointi della lista
//      temp2.duplicate = temp1.duplicate;
 //     temp2.vnum = temp1.vnum;
      list.InsertBeforeHead( temp2 );     //inserisce il nuovo vertice nella lista 
      temp1 = temp1.next;                 //avanziamo temp1, l'indice della lista da copiare
    } while (temp1 != head);
  }

  
 
  //Inverte i vertici, in modo da avere un verso antiorario-->1234 diventa 1432
  public void ReverseList()               
  {
    VertexList listcopy = new VertexList();       //creiamo una nuova VertexList
    Vertex temp1, temp2;                          //creiamo due indici temp1,temp2
    ListCopy(listcopy);                           //copiamo la lista nella nuova listcopy
    this.ClearVertexList();                       //cancelliamo la lista vecchia

    //riempiamo la lista nuova in modo appropriato
    temp1 = listcopy.head;                        //in temp1 mettiamo in vertice head
    do {
      temp2 = new Vertex();                       //in temp2 mettiamo un nuovo vertice
      temp2.v = temp1.v;                          //in temp2.v mettiamo il Pointi della lista
      InsertBeforeHead( temp2 );                  //inseriamo il vertice temp2 nella lista che avevamo cancellato
      temp1 = temp1.prev;                         //scorriamo l'indice temp1 all'indietro
    } while (temp1 != listcopy.head );
    System.out.println("Reversing list...");
  }

  




  /* 
   * Ritorna l'area del poligono formato da una lista di vertici
   */

  public int AreaPoly2()
  {
    int sum = 0;
    Vertex  a, p;
	
    p = head;      /* Fisso   */
    a = p.next;    /* Variabile */
    
    do {
      //per calcolare l'area di un poligono effettuiamo una triangolazione  
      sum += p.v.Area2( p.v, a.v, a.next.v );  
      a = a.next;
    } while ( a.next != head );
    
    System.out.println(sum);
    return sum;
  }

  
  
  /* Determina se il poligono/list è orientato in senso antiorario (ccw).
   * Esistono altri metodi per farlo ma vogliamo sfruttare AreaPoly2
   */
  
  public int Ccw ()                  //se l'area di un triangolo è positiva, i vertici sono orientati in senso antiorario
  {                                  //per un poligono facciamo la triangolazione dello stesso e calcoliamo l'area totale
    int sign = AreaPoly2(); 
    
    //se è >0 allora il verso è antiorario, orario altrimenti
    if (sign > 0 ) return 1;
    else return -1;
  }
  
  
  
  /* 
   *  CheckForConvexity()ritorna true se il poligono è convesso, false altrimenti
   */
  
  public boolean CheckForConvexity()
  {
    Vertex v = head;
    boolean flag = true;

    do {
      if ( !v.v.LeftOn( v.v, v.next.v, v.next.next.v )) {          //per ogni tripla di punti controlla se il terzo è a sinistra della retta passante per i primi due
	flag = false;                                              //presuppone che i vertici del poligono siano orientati in verso antiorario
	break;                                                     //usiamo LeftOn e non Left perchè l'area tra tre punti può anche essere zero, cioè il caso in cui i 3 punti siano collineari
      }
      v= v.next;
    } while (v != head);
    
    return flag;
  }


 
}





